From 15bb102195405440c7b28edd849ab619f6e91529 Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Tue, 22 Jun 2004 20:06:52 +0000 Subject: [PATCH] bitkeeper revision 1.999.1.1 (40d8915c_Ar85TqYtbqEdZrkpMNL_A) Move interface bridging out of xenlinux kernel into xend. --- .rootkeys | 1 + .../xen/drivers/netif/backend/interface.c | 10 + tools/xenmgr/lib/XendBridge.py | 182 ++++++++++++++++++ tools/xenmgr/lib/XendDomain.py | 2 +- tools/xenmgr/lib/XendDomainInfo.py | 28 ++- tools/xenmgr/lib/server/SrvConsoleServer.py | 8 +- tools/xenmgr/lib/server/SrvServer.py | 11 +- tools/xenmgr/lib/server/blkif.py | 14 ++ tools/xenmgr/lib/server/netif.py | 44 ++++- tools/xenmgr/netfix | 124 ++---------- 10 files changed, 300 insertions(+), 124 deletions(-) create mode 100644 tools/xenmgr/lib/XendBridge.py diff --git a/.rootkeys b/.rootkeys index fe4c4ae455..acbd6201cb 100644 --- a/.rootkeys +++ b/.rootkeys @@ -231,6 +231,7 @@ 40c9c468Um_qc66OQeLEceIz1pgD5g tools/xenmgr/lib/EventServer.py 40c9c468U8EVl0d3G--8YXVg6VJD3g tools/xenmgr/lib/EventTypes.py 40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/xenmgr/lib/PrettyPrint.py +40d8915cyoVA0hJxiBFNymL7YvDaRg tools/xenmgr/lib/XendBridge.py 40c9c4688m3eqnC8fhLu1APm36VOVA tools/xenmgr/lib/XendClient.py 40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/xenmgr/lib/XendConsole.py 40c9c468WnXs6eOUSff23IIGI4kMfQ tools/xenmgr/lib/XendDB.py diff --git a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/interface.c b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/interface.c index 09b4a1f0f0..cc20e780ce 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/interface.c +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/interface.c @@ -13,8 +13,10 @@ #define NETIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(NETIF_HASHSZ-1)) static netif_t *netif_hash[NETIF_HASHSZ]; +#ifdef XEN_BRIDGE static struct net_device *bridge_dev; static struct net_bridge *bridge_br; +#endif netif_t *netif_find_by_handle(domid_t domid, unsigned int handle) { @@ -38,7 +40,9 @@ void __netif_disconnect_complete(netif_t *netif) unbind_evtchn_from_irq(netif->evtchn); vfree(netif->tx); /* Frees netif->rx as well. */ rtnl_lock(); +#ifdef XEN_BRIDGE (void)br_del_if(bridge_br, netif->dev); +#endif (void)dev_close(netif->dev); rtnl_unlock(); @@ -240,6 +244,7 @@ void netif_connect(netif_be_connect_t *connect) rtnl_lock(); (void)dev_open(netif->dev); +#ifdef XEN_BRIDGE (void)br_add_if(bridge_br, netif->dev); /* @@ -254,6 +259,7 @@ void netif_connect(netif_be_connect_t *connect) (void)dev_open(eth0_dev); (void)br_add_if(bridge_br, eth0_dev); } +#endif rtnl_unlock(); @@ -295,6 +301,7 @@ int netif_disconnect(netif_be_disconnect_t *disconnect, u8 rsp_id) void netif_interface_init(void) { memset(netif_hash, 0, sizeof(netif_hash)); +#ifdef XEN_BRIDGE if ( br_add_bridge("nbe-br") != 0 ) BUG(); bridge_dev = __dev_get_by_name("nbe-br"); @@ -302,14 +309,17 @@ void netif_interface_init(void) bridge_br->bridge_hello_time = bridge_br->hello_time = 0; bridge_br->bridge_forward_delay = bridge_br->forward_delay = 0; bridge_br->stp_enabled = 0; +#endif } #ifndef CONFIG_BRIDGE #error Must configure Ethernet bridging in Network Options #endif +#ifndef XEN_BRIDGE EXPORT_SYMBOL(br_add_bridge); EXPORT_SYMBOL(br_del_bridge); EXPORT_SYMBOL(br_add_if); EXPORT_SYMBOL(br_del_if); EXPORT_SYMBOL(br_get_bridge_ifindices); EXPORT_SYMBOL(br_get_port_ifindices); +#endif diff --git a/tools/xenmgr/lib/XendBridge.py b/tools/xenmgr/lib/XendBridge.py new file mode 100644 index 0000000000..1be802477d --- /dev/null +++ b/tools/xenmgr/lib/XendBridge.py @@ -0,0 +1,182 @@ +"""Bridge control utilities. +""" +import os +import os.path +import re +import sys + +from xenmgr import XendRoot +xroot = XendRoot.instance() + +os.defpath = os.defpath + ':/sbin:/usr/sbin:/usr/local/sbin' +CMD_IFCONFIG = 'ifconfig' +CMD_ROUTE = 'route' +CMD_BRCTL = 'brctl' + +DEFAULT_BRIDGE = 'nbe-br' +DEFAULT_INTERFACE = 'eth0' + +opts = None + +class Opts: + + def __init__(self, defaults): + for (k, v) in defaults.items(): + setattr(self, k, v) + pass + +def cmd(p, s): + """Print and execute command 'p' with args 's'. + """ + global opts + c = p + ' ' + s + if opts.verbose: print c + if not opts.dryrun: + os.system(c) + +def default_bridge(): + return xroot.get_config_value('bridge', DEFAULT_BRIDGE) + +def default_interface(): + return xroot.get_config_value('interface', DEFAULT_INTERFACE) + +def vif_dev(dom, vif): + """Return the name of the network interface for vif on domain dom. + """ + return "vif%d.%d" % (dom, vif) + +def vif_bridge_add(dom, vif, bridge=None): + """Add the network interface for vif on dom to a bridge. + """ + if not bridge: bridge = default_bridge() + d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) } + cmd(CMD_BRCTL, 'addif %(bridge)s %(vif)s' % d) + return bridge + +def vif_bridge_rem(dom, vif, bridge=None): + """Remove the network interface for vif on dom from a bridge. + """ + if not bridge: bridge = default_bridge() + print 'vif_bridge_rem>', dom, vif, bridge + d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) } + cmd(CMD_BRCTL, 'delif %(bridge)s %(vif)s' % d) + +def bridge_create(bridge=None, **kwd): + """Create a bridge. + Defaults hello time to 0, forward delay to 0 and stp off. + """ + if not bridge: bridge = default_bridge() + cmd(CMD_BRCTL, 'addbr %s' % bridge) + if kwd.get('hello', None) is None: + kwd['hello'] = 0 + if kwd.get('fd', None) is None: + kwd['fd'] = 0 + if kwd.get('stp', None) is None: + kwd['stp'] = 'off' + bridge_set(bridge, **kwd) + +def bridge_set(bridge, hello=None, fd=None, stp=None): + """Set bridge parameters. + """ + if hello is not None: + cmd(CMD_BRCTL, 'sethello %s %d' % (bridge, hello)) + if fd is not None: + cmd(CMD_BRCTL, 'setfd %s %d' % (bridge, fd)) + if stp is not None: + cmd(CMD_BRCTL, 'stp %s %s' % (bridge, stp)) + +def bridge_del(bridge=None): + """Delete a bridge. + """ + if not bridge: bridge = default_bridge() + cmd(CMD_BRCTL, 'delbr %s' % bridge) + +def routes(): + """Return a list of the routes. + """ + fin = os.popen(CMD_ROUTE + ' -n', 'r') + routes = [] + for x in fin: + if x.startswith('Kernel'): continue + if x.startswith('Destination'): continue + x = x.strip() + y = x.split() + z = { 'destination': y[0], + 'gateway' : y[1], + 'mask' : y[2], + 'flags' : y[3], + 'metric' : y[4], + 'ref' : y[5], + 'use' : y[6], + 'interface' : y[7] } + routes.append(z) + return routes + +def ifconfig(interface): + """Return the ip config for an interface, + """ + fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r') + inetre = re.compile('\s*inet\s*addr:(?P
\S*)\s*Bcast:(?P\S*)\s*Mask:(?P\S*)') + info = None + for x in fin: + m = inetre.match(x) + if not m: continue + info = m.groupdict() + info['interface'] = interface + break + return info + +def reconfigure(interface=None, bridge=None): + """Reconfigure an interface to be attached to a bridge, and give the bridge + the IP address etc. from interface. Move the default route to the interface + to the bridge. + + If opts.create is true, creates the bridge. + """ + global opts + if not interface: interface = default_interface() + if not bridge: bridge = default_bridge() + intf_info = ifconfig(interface) + if not intf_info: + print 'Interface not found:', interface + return + if opts.create: + bridge_create(bridge) + #bridge_info = ifconfig(bridge) + #if not bridge_info: + # print 'Bridge not found:', bridge + # return + route_info = routes() + intf_info['bridge'] = bridge + intf_info['gateway'] = None + for r in route_info: + if (r['destination'] == '0.0.0.0' and + 'G' in r['flags'] and + r['interface'] == interface): + intf_info['gateway'] = r['gateway'] + if not intf_info['gateway']: + print 'Gateway not found: ', interface + return + cmd(CMD_IFCONFIG, + '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up' + % intf_info) + cmd(CMD_ROUTE, + 'add default gateway %(gateway)s dev %(bridge)s' + % intf_info) + cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info) + cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info) + +defaults = { + 'interface': default_interface(), + 'bridge' : default_bridge(), + 'verbose' : 1, + 'dryrun' : 0, + 'create' : 0, + } + +opts = Opts(defaults) + +def set_opts(val): + global opts + opts = val + return opts diff --git a/tools/xenmgr/lib/XendDomain.py b/tools/xenmgr/lib/XendDomain.py index d3cddc4e75..f236a43d80 100644 --- a/tools/xenmgr/lib/XendDomain.py +++ b/tools/xenmgr/lib/XendDomain.py @@ -8,7 +8,6 @@ import sys import Xc; xc = Xc.new() import xenctl.ip -import xenctl.vdisk import sxp import XendRoot @@ -125,6 +124,7 @@ class XendDomain: def _delete_domain(self, id, notify=1): if id in self.domain: + self.domain[id].died() if notify: eserver.inject('xend.domain.died', id) del self.domain[id] if id in self.domain_db: diff --git a/tools/xenmgr/lib/XendDomainInfo.py b/tools/xenmgr/lib/XendDomainInfo.py index 88598cd9c6..182b523d11 100644 --- a/tools/xenmgr/lib/XendDomainInfo.py +++ b/tools/xenmgr/lib/XendDomainInfo.py @@ -17,7 +17,6 @@ import os from twisted.internet import defer import Xc; xc = Xc.new() - import xenctl.ip import sxp @@ -25,6 +24,8 @@ import sxp import XendConsole xendConsole = XendConsole.instance() +import XendBridge + import server.SrvConsoleServer xend = server.SrvConsoleServer.instance() @@ -183,6 +184,18 @@ class XendDomainInfo: return 0 return xc.domain_destroy(dom=self.dom) + def died(self): + print 'died>', self.dom + self.release_vifs() + + def release_vifs(self): + print 'release_vifs>', self.dom + vifs = self.get_devices('vif') + for v in vifs: + vif = sxp.child_value(v, 'vif') + bridge = sxp.child_value(v, 'bridge') + XendBridge.vif_bridge_rem(self.dom, vif, bridge) + def show(self): """Print virtual machine info. """ @@ -264,7 +277,7 @@ def lookup_disk_uname( uname ): segments = None return segments -def make_disk(dom, uname, dev, mode, sharing): +def make_disk(dom, uname, dev, mode): """Create a virtual disk device for a domain. @returns Deferred @@ -689,10 +702,14 @@ def vm_dev_vif(vm, val, index): raise VmError('vif: vif in control domain') vif = index #todo vmac = sxp.child_value(val, "mac") - bridge = sxp.child_value(val, "bridge") # todo defer = make_vif(vm.dom, vif, vmac) def fn(id): - dev = val + ['vif', vif] + bridge = sxp.child_value(val, "bridge") + bridge = XendBridge.vif_bridge_add(vm.dom, vif, bridge) + dev = ['vif', ['vif', vif], ['bridge', bridge] ] + netdev = xend.netif_dev(vm.dom, vif) + if netdev and netdev.mac: + dev += [ 'mac', netdev.mac ] vm.add_device('vif', dev) print 'vm_dev_vif> created', dev return id @@ -715,8 +732,7 @@ def vm_dev_vbd(vm, val, index): if not dev: raise VMError('vbd: Missing dev') mode = sxp.child_value(val, 'mode', 'r') - sharing = sxp.child_value(val, 'sharing', 'rr') - defer = make_disk(vm.dom, uname, dev, mode, sharing) + defer = make_disk(vm.dom, uname, dev, mode) def fn(vbd): vm.add_device('vbd', val) return vbd diff --git a/tools/xenmgr/lib/server/SrvConsoleServer.py b/tools/xenmgr/lib/server/SrvConsoleServer.py index 21d39140b2..7179a0d1d4 100644 --- a/tools/xenmgr/lib/server/SrvConsoleServer.py +++ b/tools/xenmgr/lib/server/SrvConsoleServer.py @@ -549,7 +549,7 @@ class Daemon: self.listenEvent() self.listenNotifier() self.listenVirq() - SrvServer.create() + SrvServer.create(bridge=1) reactor.run() def createFactories(self): @@ -602,6 +602,9 @@ class Daemon: d = self.blkifCF.createInstance(dom) return d + def blkif_dev(self, dom, vdev): + return self.blkifCF.getDomainDevice(dom, vdev) + def blkif_dev_create(self, dom, vdev, mode, segment): """Create a block device. @@ -641,6 +644,9 @@ class Daemon: d = ctrl.attach_device(vif, vmac) return d + def netif_dev(self, dom, vif): + return self.netifCF.getDomainDevice(dom, vif) + def console_create(self, dom, console_port=None): """Create a console for a domain. """ diff --git a/tools/xenmgr/lib/server/SrvServer.py b/tools/xenmgr/lib/server/SrvServer.py index a42219b620..d507c2002b 100644 --- a/tools/xenmgr/lib/server/SrvServer.py +++ b/tools/xenmgr/lib/server/SrvServer.py @@ -32,17 +32,24 @@ from twisted.internet import reactor from xenmgr import XendRoot xroot = XendRoot.instance() +from xenmgr import XendBridge + from SrvRoot import SrvRoot -def create(port=None, interface=None): +def create(port=None, interface=None, bridge=0): if port is None: port = 8000 if interface is None: interface = '' + if bridge or xroot.rebooted: + init_bridge() root = resource.Resource() xend = SrvRoot() root.putChild('xend', xend) site = server.Site(root) reactor.listenTCP(port, site, interface=interface) - + +def init_bridge(): + XendBridge.bridge_create() + XendBridge.reconfigure() def main(port=None, interface=None): create(port, interface) diff --git a/tools/xenmgr/lib/server/blkif.py b/tools/xenmgr/lib/server/blkif.py index 7ffa35179d..8da827baa9 100755 --- a/tools/xenmgr/lib/server/blkif.py +++ b/tools/xenmgr/lib/server/blkif.py @@ -33,6 +33,14 @@ class BlkifControllerFactory(controller.ControllerFactory): blkif.send_be_create() return d + def getDomainDevices(self, dom): + blkif = self.getInstanceByDom(dom) + return (blkif and blkif.getDevices()) or [] + + def getDomainDevice(self, dom, vdev): + blkif = self.getInstanceByDom(dom) + return (blkif and blkif.getDevice(vdev)) or None + def setControlDomain(self, dom): if self.dom == dom: return self.deregisterChannel() @@ -146,6 +154,12 @@ class BlkifController(controller.Controller): self.registerChannel() #print 'BlkifController<', 'dom=', self.dom, 'idx=', self.idx + def getDevices(self): + return self.devices.values() + + def getDevice(self, vdev): + return self.devices.get(vdev) + def attach_device(self, vdev, mode, segment): """Attach a device to the specified interface. """ diff --git a/tools/xenmgr/lib/server/netif.py b/tools/xenmgr/lib/server/netif.py index 13bdd96486..f3da86ba82 100755 --- a/tools/xenmgr/lib/server/netif.py +++ b/tools/xenmgr/lib/server/netif.py @@ -31,6 +31,14 @@ class NetifControllerFactory(controller.ControllerFactory): netif = NetifController(self, dom) self.addInstance(netif) return netif + + def getDomainDevices(self, dom): + netif = self.getInstanceByDom(dom) + return (netif and netif.getDevices()) or [] + + def getDomainDevice(self, dom, vif): + netif = self.getInstanceByDom(dom) + return (netif and netif.getDevice(vif)) or None def setControlDomain(self, dom): """Set the 'back-end' device driver domain. @@ -98,6 +106,11 @@ class NetDev: self.vif = vif self.mac = mac self.evtchn = None + + def sxpr(self): + vif = str(self.vif) + mac = ':'.join(map(lambda x: "%x" % x, self.mac)) + return ['netif', ['vif', vif], ['mac', mac]] class NetifController(controller.Controller): """Network interface controller. Handles all network devices for a domain. @@ -135,20 +148,37 @@ class NetifController(controller.Controller): random.randint(0x00, 0xff) ] return mac - def attach_device(self, vif, vmac): - """Attach a network device. - If vmac is None a random mac address is assigned. + def lostChannel(self): + print 'NetifController>lostChannel>', 'dom=', self.dom + #for vif in self.devices: + # self.send_be_destroy(vif) + controller.Controller.lostChannel(self) - @param vif interface index - @param vmac mac address (string) - """ + def getDevices(self): + return self.devices.values() + + def getDevice(self, vif): + return self.devices.get(vif) + + def addDevice(self, vif, vmac): if vmac is None: mac = self.randomMAC() else: mac = [ int(x, 16) for x in vmac.split(':') ] if len(mac) != 6: raise ValueError("invalid mac") #print "attach_device>", "vif=", vif, "mac=", mac - self.devices[vif] = NetDev(vif, mac) + dev = NetDev(vif, mac) + self.devices[vif] = dev + return dev + + def attach_device(self, vif, vmac): + """Attach a network device. + If vmac is None a random mac address is assigned. + + @param vif interface index + @param vmac mac address (string) + """ + self.addDevice(vif, vmac) d = self.factory.addDeferred() self.send_be_create(vif) return d diff --git a/tools/xenmgr/netfix b/tools/xenmgr/netfix index 65c354490d..998a78a0d9 100644 --- a/tools/xenmgr/netfix +++ b/tools/xenmgr/netfix @@ -3,102 +3,15 @@ # Copyright (C) 2004 Mike Wray #============================================================================ # Move the IP address from eth0 onto the Xen bridge (nbe-br). -# Works best if the bridge control utils (brctl) have been installed. +# Only works if the bridge control utils (brctl) have been installed. #============================================================================ -import os -import os.path -import re -import sys from getopt import getopt +from xenmgr.XendBridge import * -os.defpath = os.defpath+':/sbin:/usr/sbin:/usr/local/sbin' -CMD_IFCONFIG = 'ifconfig' -CMD_ROUTE = 'route' -CMD_BRCTL = 'brctl' - -def routes(): - """Return a list of the routes. - """ - fin = os.popen(CMD_ROUTE + ' -n', 'r') - routes = [] - for x in fin: - if x.startswith('Kernel'): continue - if x.startswith('Destination'): continue - x = x.strip() - y = x.split() - z = { 'destination': y[0], - 'gateway' : y[1], - 'mask' : y[2], - 'flags' : y[3], - 'metric' : y[4], - 'ref' : y[5], - 'use' : y[6], - 'interface' : y[7] } - routes.append(z) - return routes - -def cmd(p, s): - """Print and execute command 'p' with args 's'. - """ - global opts - c = p + ' ' + s - if opts.verbose: print c - if not opts.dryrun: - os.system(c) - -def ifconfig(interface): - """Return the ip config for an interface, - """ - fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r') - inetre = re.compile('\s*inet\s*addr:(?P
\S*)\s*Bcast:(?P\S*)\s*Mask:(?P\S*)') - info = None - for x in fin: - m = inetre.match(x) - if not m: continue - info = m.groupdict() - info['interface'] = interface - break - return info - -def reconfigure(interface, bridge): - """Reconfigure an interface to be attached to a bridge, and give the bridge - the IP address etc. from interface. Move the default route to the interface - to the bridge. - """ - intf_info = ifconfig(interface) - if not intf_info: - print 'Interface not found:', interface - return - #bridge_info = ifconfig(bridge) - #if not bridge_info: - # print 'Bridge not found:', bridge - # return - route_info = routes() - intf_info['bridge'] = bridge - intf_info['gateway'] = None - for r in route_info: - if (r['destination'] == '0.0.0.0' and - 'G' in r['flags'] and - r['interface'] == interface): - intf_info['gateway'] = r['gateway'] - if not intf_info['gateway']: - print 'Gateway not found: ', interface - return - cmd(CMD_IFCONFIG, '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up' % intf_info) - cmd(CMD_ROUTE, 'add default gateway %(gateway)s dev %(bridge)s' % intf_info) - cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info) - cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info) - -defaults = { - 'interface': 'eth0', - 'bridge' : 'nbe-br', - 'verbose' : 1, - 'dryrun' : 0, - } - -short_options = 'hvqni:b:' -long_options = ['help', 'verbose', 'quiet', 'interface=', 'bridge='] +short_options = 'hvqni:b:c' +long_options = ['help', 'verbose', 'quiet', + 'interface=', 'bridge=', 'create'] def usage(): print """Usage: @@ -107,12 +20,13 @@ def usage(): Reconfigure routing so that has the IP address from . This lets IP carry on working when is attached to for virtual networking. - If brctl is available, is added to , + Uses brctl to add to , so this can be run before any domains have been created. """ % sys.argv[0] print """ -i, --interface interface, default %(interface)s. -b, --bridge bridge, default %(bridge)s. + -c, --create create the bridge. -v, --verbose Print commands. -q, --quiet Don't print commands. -n, --dry-run Don't execute commands. @@ -120,32 +34,28 @@ def usage(): """ % defaults sys.exit(1) -class Opts: - - def __init__(self, defaults): - for (k, v) in defaults.items(): - setattr(self, k, v) - pass def main(): - global opts - opts = Opts(defaults) + lopts = set_opts(Opts(defaults)) + lopts.dryrun = 0 (options, args) = getopt(sys.argv[1:], short_options, long_options) if args: usage() for k, v in options: if k in ['-h', '--help']: usage() + elif k in ['-c', '--create']: + lopts.create = 1 elif k in ['-i', '--interface']: - opts.interface = v + lopts.interface = v elif k in ['-b', '--bridge']: - opts.bridge = v + lopts.bridge = v elif k in ['-q', '--quiet']: - opts.verbose = 0 + lopts.verbose = 0 elif k in ['-v', '--verbose']: - opts.verbose = 1 + lopts.verbose = 1 elif k in ['-n', '--dry-run']: - opts.dryrun = 1 - reconfigure(opts.interface, opts.bridge) + lopts.dryrun = 1 + reconfigure(lopts.interface, lopts.bridge) if __name__ == '__main__': main() -- 2.30.2